import json
from urllib.parse import parse_qs
from urllib.request import urlopen

from django.conf import settings
from urllib import parse
import logging
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, BadData

from itsdangerous import Serializer

from oauth import constants
from .exceptions import OAuthQQAPIError

logger = logging.getLogger('django')


class OAuthQQ(object):
    """
    QQ认证辅助工具类
    """
    def __init__(self, client_id=None, client_secret=None,redirect_uri=None, state=None):

        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI
        self.state = state or settings.QQ_STATE
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET

    def get_qq_login_url(self):
        """
        获取QQ登录的网址
        :return: QQ登录的网址
        """
        url = 'https://graph.qq.com/oauth2.0/authorize?'
        params = {
            'response_type': 'code',
            'client_id': self.client_id,
            'redirect_uri': self.redirect_uri,
            'state': self.state
        }
        url += parse.urlencode(params)

        return url

    def get_access_token(self, code):
        """
        获取 access_token
        :param code:
        :return:
        """
        params = {
            'grant_type': 'authorization_code',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code,
            'redirect_uri': self.redirect_uri
        }
        url = 'https://graph.qq.com/oauth2.0/token?'
        url += parse.urlencode(params)

        try:
            response = urlopen(url)
            response_data = response.read().decode()
            data = parse_qs(response_data)
        except Exception as e:
            logging.error('访问腾讯服务器,获取access_token异常 %s' % e)
            raise OAuthQQAPIError

        access_token = data.get('access_token', None)

        if not access_token:
            logger.error('code=%s msg=%s' % (data.get('code'), data.get('mag')))
            raise OAuthQQAPIError

        return access_token[0]

    def get_openid(self, access_token):
        """
        获取登录用户的openid
        :param access_token:
        :return:
        """
        url = 'https://graph.qq.com/oauth2.0/me?access_token='+ access_token

        try:
            response = urlopen(url)
            response_data = response.read().decode()
            # 返回的数据 callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
            data = json.loads(response_data[10:-4])
        except Exception as e:
            logger.error("获取openid时出错 %s" % e)
            raise OAuthQQAPIError
        else:
            openid = data.get('openid', None)
            return openid

    def generate_bind_user_access_token(self, openid):
        """生成保存用户数据的token"""
        serializer = TJWSSerializer(settings.SECRET_KEY, constants.BIND_USER_ACCESS_TOKEN_EXPIRES)
        token = serializer.dumps({'openid': openid})
        return token.decode()

    @staticmethod
    def check_bind_user_access_token(access_token):
        serializer = TJWSSerializer(settings.SECRET_KEY, constants.BIND_USER_ACCESS_TOKEN_EXPIRES)
        try:
            data = serializer.loads(access_token)
        except BadData:
            return None
        else:
            return data['openid']

